#include "main.h"
#include <stdlib.h>

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);

	ParseForArguments();
	LoadSettings();

	hWnd = InitializeWindow(hInstance);
	InitializeTrayIcon();

	if (InitializeHook() == FALSE)
		return -1;
	
	//-----------------------------
	//Run message loop:
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	WriteEventLogEntry(L"Cleaning up ScrollPP.", EVENTLOG_INFORMATION_TYPE);

	ShutdownWindow();

	if (ShutdownHook() == FALSE)
		return -1;

	WriteEventLogEntry(L"Scroll++ was successfully shutdown.", EVENTLOG_INFORMATION_TYPE);

	return 0;
}

DWORD CALLBACK ExitMutexProc(LPVOID data)
{
	DWORD* mainThreadId = (DWORD*)data;
	DWORD result = WaitForSingleObject(hMutex, INFINITE);
	if (result != ERROR_SUCCESS)
		WriteErrorLogEntry(L"WaitForSingleObject", result);

	PostThreadMessage(*mainThreadId, WM_QUIT, 0, 0);

	return 0;
}


LRESULT CALLBACK WndProc (HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	switch(msg)
	{
	case WM_SYSICON:
		if(lparam == WM_LBUTTONUP && _isTrayIconLMouseButtonDown)
		{
			_disableScrollPP = !_disableScrollPP;
			_isTrayIconLMouseButtonDown = FALSE;
			UpdateTrayIcon();

			//save it
			HKEY key = OpenKey(HKEY_CURRENT_USER, REG_KEY_Options);
			SetVal(key, REG_DisableScrollPP, _disableScrollPP);
			RegCloseKey(key);
		}
		else if(lparam == WM_LBUTTONDOWN)
		{
			_isTrayIconLMouseButtonDown = TRUE;
		}
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		if (msg == WM_TASKBARCREATED)
		{
			Sleep(1500); //wait to be sure that explorer is already initialized
			InitializeTrayIcon();
		}
	}

	return DefWindowProc(hWnd, msg, wparam, lparam);
}

void InitializeTrayIcon()
{
	if (hWnd)
	{
		if (CreateTrayIcon(hWnd))
			UpdateTrayIcon();
	}
}

void UpdateTrayIcon()
{
	if (_disableScrollPP)
	{
		SetTrayIconToolTip(ScrollPPDisabledToolTip);
		SetTrayIconIcon(IDI_ICON_RED);
	}
	else
	{
		SetTrayIconToolTip(ScrollPPEnabledToolTip);
		SetTrayIconIcon(IDI_ICON_GREEN);
	}
}

void ParseForArguments()
{
	//Parse args:
	int argc;
	LPWSTR* cmd = CommandLineToArgvW(GetCommandLine(), &argc);

	for (int i = 0; i < argc; i++)
	{
		if (wcsncmp(cmd[i], L"-se:", 4) == 0)
		{
			LPWSTR mutexName = NULL;

			mutexName = cmd[i];
			mutexName += 4;

			WriteErrorLogEntry(cmd[i], 0);
			WriteErrorLogEntry(mutexName, 0);

			hMutex = CreateMutex(NULL, FALSE, mutexName);
			if (hMutex == NULL)
			{
				WriteErrorLogEntry(L"Could not create mutex. CreateMutex", GetLastError());
			}
			else if ((GetLastError() != ERROR_ALREADY_EXISTS))
			{
				WriteEventLogEntry(L"Could not open existing mutex.", EVENTLOG_WARNING_TYPE);
				CloseHandle(hMutex);
				hMutex = NULL;
			}
			else
			{
				static DWORD currentThreadId = GetCurrentThreadId();
				QueueUserWorkItem(&ExitMutexProc, &currentThreadId, WT_EXECUTELONGFUNCTION);
			}

			break;
		}
	}

	LocalFree(cmd);
}

void LoadSettings()
{
	//-----------------------------
	//Query settings:
	HKEY key = OpenKey(HKEY_CURRENT_USER, REG_KEY_Options);
	_disableScrollPP = GetVal(key, REG_DisableScrollPP);
	RegCloseKey(key);
}

HWND InitializeWindow(HINSTANCE hInstance)
{
	HWND result = NULL;

	//-----------------------------
	//Create Window:
	WNDCLASSEX wndClass;
	ZeroMemory(&wndClass, sizeof(wndClass));
	wndClass.hInstance = hInstance;
	wndClass.lpszClassName = CLASS_NAME;
	wndClass.lpfnWndProc = WndProc;

	wndClass.cbSize = sizeof(WNDCLASSEX);
	if (RegisterClassEx(&wndClass))
	{
		result = CreateWindowEx(0, CLASS_NAME, L"Scroll++ Message Window", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
	}

	WM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
	SendNotifyMessage(HWND_BROADCAST, WM_TASKBARCREATED, 0, 0);
	BOOL success = ChangeWindowMessageFilter(WM_TASKBARCREATED, MSGFLT_ADD);

	return result;
}

void ShutdownWindow()
{
	if (hWnd)
	{
		BOOL result = DestroyTrayIcon();
		result = DestroyWindow(hWnd); //destroy tray icon
	}
}